// to avoid race condition and mix the sessions,
// never send two Ajax request one after another.
// The second Ajax request should be sent when
// the first call response is received
// see http://www.chipmunkninja.com/article/asyncsessions

// if a tag is in, the list is filtered by this tag
var tag_state;
tag_state = new Array;

// remember the timer for the tag selection
var timeo;

// notes window
var noteswin = "";

// keys that do not display the save button
var ignore_keys;
ignore_keys = new Array('9', '16', '17', '18', '27', '35', '36', '39', '37', '38', '40', '116');

/*

This introduce a bug in prototype's Sortable class

Array.prototype.include = function(el) {
    for(var i=0; i<this.length;i++)
        if(this[i]==el) return i;
    return -1;
}

Array.prototype.remove = function(el) {
    for(var i=0; i<this.length;i++) {
        if(this[i]==el) this.splice(i,1);
    }
}

*/

// see http://blog.stevenlevithan.com/archives/faster-trim-javascript
function trim (str) {
	var	s = str.replace(/^\s\s*/, ''),
		ws = /\s/,
		i = s.length;
	while (ws.test(s.charAt(--i))){};
	return s.slice(0, i + 1);
}

/*
String.prototype.sanitize = function() {
    for(var i=0; i<this.length;i++) {
        if(this[i]==' ') this[i]='_';
    }
}
*/

function notes(id){
  var win = new Window({
   className: "dialog",
   title: "Notes",
   width:650,
   height:400,
   zIndex: 150,
   url: "/notes/show/" + id,
   showEffectOptions: {duration:1}});
  win.showCenter();
}

function qa_complete() {
  $('qat').value = '';
  }

//var qa = null;

function quick_add(){
  qa = new Window({
   className: "dialog",
   title: "Add a task",
   top:20, left:100,
   width:450,
   height:100,
   zIndex: 150,
   showEffect:Effect.BlindDown,
   hideEffect:Effect.BlindUp,
   showEffectOptions: {duration:0.2},
   hideEffectOptions: {duration:0.2}
   });

  ajax = 'new Ajax.Updater("qa","/task/quick_add",{asynchronous:true, evalScripts:true, parameters:Form.serialize(this), complete:qa_complete(),insertion: Insertion.Top});return false;';
  text = "<form method='post' onsubmit='"+ajax+"'><div><input id='qat' name='t' size=50/> press enter</div></form><ul id='qa' class='mylist'></ul>";
  qa.setHTMLContent(text);
  qa.setStatusBar("Quickly add a new task in your inbox");
  qa.setDestroyOnClose();
  qa.show();
}

function show_qa() {
  quick_add();
  }

function ajax_eval(url) {
  new Ajax.Request(url, {
    asynchronous:true,
    evalScripts:true,
    onComplete: function(r){
      eval(r.responseText);
      }
    });
  }

// remember the id in the session
function cut(id,item_name) {
  str = '/task/cut/'+id+'?item_name='+item_name;
  ajax_eval(str);
  }
  
// paste the element remembered in the session  
function paste(id, item_name) {
  str = '/task/paste/'+id+'?item_name='+item_name;
  ajax_eval(str);
  }
  
function paste_anim(from_name, to_name, from_txt, to_txt, cut_name, sel_task) {
  var f = $(from_name);
  if(f) f.replace(from_txt);
  //else alert("Paste error: from_name = "+from_name);
    
  var t;
  if(to_name=='') { // paste to root
    t = $('taskslist');
    t.insert({ top: to_txt });
    }
  else {
    if(sel_task==1) { // to_name isn't empty, we are not copying into root, but if sel_task, we must insert it into taskslist
      t = $('taskslist');
      t.insert({ top: to_txt });
      }
    else {
      t = $(to_name);
      if(t) t.replace(to_txt);
      }
    }
    
  var cut = $(cut_name);
  if(cut)  new Effect.Highlight(cut,{duration:4});
  }
  
function set_state(state,id) {
  new Ajax.Updater("task","/inbox/save/"+id+"?s="+state,{asynchronous:true, evalScripts:true});
  }

function expand(task_id,item_name) {
  $('sub_'+item_name+'_'+task_id).show();
  var on_click = "collapse('"+task_id+"','"+item_name+"');return false;";
  $('collapse_'+item_name+'_'+task_id).update('<a href="#" onclick="'+on_click+'"><img src="/images/collapse.gif" width=12></a>');
  }

function collapse(task_id,item_name) {
  $('sub_'+item_name+'_'+task_id).hide();
  on_click = "expand('"+task_id+"','"+item_name+"');return false;";
  $('collapse_'+item_name+'_'+task_id).update('<a href="#" onclick="'+on_click+'"><img src="/images/expand.gif" width=12></a>');
  }

function set_to_loading(el_name) {
  $(el_name).src = '/images/loading.gif';
  }

// edit a task
function edit(id, item_name) {
    set_to_loading('e_'+item_name+ '_' + id);
    new Ajax.Request('/task/edit/'+id+'?item_name='+item_name, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
            $(item_name + '_' + id).update(r.responseText);
        }
    });
}

// add a sub tasks
function add_sub(id, item_name) {
    $('a_'+item_name+'_'+ id).src = '/images/loading.gif';
    new Ajax.Request('/task/add_sub/'+id+'?item_name='+item_name, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
            new Insertion.Top('sub_'+item_name+'_'+id, r.responseText);
            $('a_'+item_name+'_'+ id).src = '/images/add.png';
        }
    });
  }

// TODO
function demote(id){
    $('loading').src = '/images/loading.gif';
    new Ajax.Request('/task/demote/' + id, {
        asynchronous: true,
        evalScripts: true,
        parameters: Sortable.serialize('taskslist'),
        onComplete: function(r){
            $('taskslist').update(r.responseText);
            recreate_sortable('taskslist');
        }
    });
    return false;
}

function unselect_all_tag()   {
  for(i=tag_state.length-1;i>=0;i--) {
    tag = tag_state[i];
    toggle_tag_state(tag);
    update_tag_display(tag);
    }
  }
  
function disp_sub(id){
    if(id!=0 && (el = $('ds'+id))) el.src='/images/loading.gif';
    unselect_all_tag();
    var change_page = 0
    if(!$('taskcontent')) change_page = 1;
    new Ajax.Request('/task/disp_sub/' + id + '?cp='+change_page, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
          eval(r.responseText);
        }
    });
    return false;
}

function goto_bm(id){
    var change_page = 0
    if(!$('taskcontent')) change_page = 1;
    unselect_all_tag();
    new Ajax.Request('/task/goto_bm/' + id + '?cp='+change_page, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
          eval(r.responseText);
        }
    });
    return false;
}

function disp_del_task(id, item_name){
  if (id == '-1') {alert('Error: Task not found');return;}
  else if (id == '-2') {alert('Error: Task can not be deleted');return;}
  else if(String(id) != String(parseInt(id))) {alert('Error: '+String(id));return;}
  new Effect.BlindUp($(item_name+'_'+id));
  }

function asking_delete(id, item_name) {
  new Ajax.Request('/task/asking_delete/'+id+'?item_name='+item_name, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(r){
        eval(r.responseText);
      }
  });
}

function delete_confirm(txt) {
  var win = new Window({
   id: 'confirm_delete',
   destroyOnClose: true,
   className: "dialog",
   title: "Alert ! Delete confirmation needed.",
   width:650,
   height:400,
   zIndex: 160,
   showEffectOptions: {duration:0.2}});
  win.setHTMLContent(txt) ;
  win.showCenter();
  }

function delete_confirmed(id,item_name) {
  var el = $('de_'+item_name+'_'+id).src = '/images/loading.gif';
  new Ajax.Request('/task/delete/'+id, {
      onComplete: function(r){
        disp_del_task(r.responseText, item_name);
      }
  });
}

function del(id, item_name){
  if (confirm('Delete this task ?\n\"' + $('t' + id).value + '\"')) {
      var el = $('de_'+item_name+'_'+id).src = '/images/loading.gif';
      new Ajax.Request('/task/delete/'+id, {
          onComplete: function(r){
            disp_del_task(r.responseText, item_name);
          }
      });
  }
  return false;
}

// update the task's deadline div
function update_task_deadline(task_id, deadline){
  $('deadline' + task_id).update(deadline);
}

// update the task's tags div
function update_task_tags(task_id, tags){
  $('tag' + task_id).update(tags);
}

// display all project tags
function display_tags(str) {
  var el = $('tags');
  if(!el) return;
  el.update(str);
  update_all_tag_display();
}

// as js string's size can not be > 1024
function expand_tags(str, path, pid) {
  var el = $('tags');
  if(!el) return;
  if(pid=='') {alert('no project id in expand_tags');return;}
  rv = '';  
  tags = str.split('|');
  for(var i=0; i < tags.length;i++) {
    t = trim(tags[i]);
    if(t=='') continue;
    rv += '<div id="tag_filter_'+t+'" class="tag" onclick="toggle_tag(\''+path+'\','+pid+',\''+t+'\')">'+t+'</div> ';
    }
  el.update(rv);
  update_all_tag_display();
  }

// update the display by filtering by tags
function filter_tasks(controller,project_id,tags) {
  $('loading').src = '/images/loading.gif';
  new Ajax.Request('/'+controller+'/filter_by_tag/' + project_id + '?t=' + tags, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(request){
        display_tasks(request.responseText);
      }});
}

function update_tag_display(tag) {
  var el = $('tag_filter_' + tag);
  if(!el) return; // happens when the last task with this tag has been done
  if(tag_state.indexOf(tag)==-1)
      el.className = 'tag';
  else
      el.className = 'tag on';
}

function toggle_tag_state(tag) {
  if(tag_state.indexOf(tag)==-1)
      tag_state.push(tag);
  else
      tag_state = tag_state.without(tag);
}

// update tag_state's tag display
function update_all_tag_display() {
  tag_state._each(update_tag_display)
}

// filter by tag
function toggle_tag(controller,project_id, tag) {
  // change style
  clearTimeout(timeo);
  var el = $('loading')
  el.src = '/images/icon_clock.gif';
  el.show();
  toggle_tag_state(tag);
  update_tag_display(tag);
  timeo = setTimeout("filter_tasks('"+controller+"',"+project_id+", '"+tag_state.join(',')+"')",1000);
  }

// done     : is the task done ?
// done_diff: did the done status changed ?
function saved(id, item_name, txt, done, done_diff) {
  //if(!item_name) alert('item_name not defined')
  //var el = $('s' + id);
  //new Effect.Fade(el);
  var el = $(item_name+'_'+id);
  if(!el) {alert('no item named '+item_name+'_'+id);return;}
  el.replace(txt);
//    TODO: all was commented out because of the new subtasking system
//    var to;
//    if (done) {
//        to = $('taskdoneul');
//        if(done_diff) {
        //$('done_on_'+id).content("done just now");
        // if we done the last task tagged and if this tag was in the tag state,
        // then it will never be removed from the tag state
        // so we clear it now
        // TODO: check if this task was the last task with this tag
//          tag_state.clear();
//          }
//        }
//    else  {
//        to = $('taskslist');
        //if(done_diff) $('done_on_'+id).content("undone");
//        }
//    if (el.parentNode != to) 
//        to.insertBefore(el, to.firstChild);
  mover('');
  recreate_sortable('taskslist');
  new Effect.Highlight(el);
  return false;
}

function save(id, item_name, createproject){
  if (String(createproject) == "undefined") 
      createproject = 0;
    if (String(item_name) == "undefined" || String(item_name) == "") {
      item_name = 'item';
      alert('item_name not given, default to "item"');
      }
  //if ($('p' + id).value == '') {
  //   alert('You must assign this task to a project. Type the name of the project this task belongs to in the first field. If the project does not exists, it will be created.');
  //    return false;
  //}
  var el = $('s' + id).src = '/images/loading.gif';
  new Ajax.Request('/task/save/'+id+'?item_name='+item_name, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(r){
          eval(r.responseText)
      },
      parameters: Form.serialize(item_name+'_'+id) + "&C=" + createproject
  });
  return false;
  }

function setclass(c, i){
    $('p' + i).className = c;
    $('t' + i).className = c;
    $('r' + i).className = c;
    $('pr' + i).className = c;
    $('da' + i).className = c;
}

function cancel_edit(i, item) {
  new Ajax.Updater(item+'_'+i, '/task/close/'+i, {asynchronous:true, evalScripts:true});
  return false;
  }

function handle_key(i,item,event) {
  event = event || window.event;
  if(event != null) {
    //event.preventDefault();
    var key = event.keyCode || event.which;
    //alert(key);
    if(ignore_keys.indexOf(key)!=-1) 
      return false;
    if(event.ctrlKey && (key == 67)) 
      return false; // Ctrl-C
    if(event.ctrlKey && (key == 65)) 
      return false; // Ctrl-A
    if (event.shiftKey && (key == 13)) { // Shift-Enter
      event.preventDefault();
      $('next_'+i).checked = true;
      save(i,item);
      return false;
      } 
    if (event.ctrlKey && (key == 13)) { // Ctrl-Enter
      event.preventDefault();
      save(i,item);
      return false;
      } 
    if (key == 27) { // Escape
      event.preventDefault();
      return cancel_edit(i,item);
      } 
    }
  return true;
  }

function change(i, event){
  // change style if done
  el1 = $('d' + i);
  el2 = $('givenup' + i);
  if(!el1 && !el2) return false; //  return now if there is no done checkbox
  if (el1.checked || el2.checked) setclass('done', i);
  else            setclass('', i);
  return false;
  }

function recreate_sortable(el){
  //Sortable.destroy(el);
  Sortable.create(el, {
    onUpdate: function(){
      new Ajax.Request('/task/order', {
        asynchronous: true,
        evalScripts: true,
        parameters: Sortable.serialize(el)
        });
      }
    });
  }

function displaynew(id, str){
  Element.hide('loading');
  new Insertion.Top('taskslist', str);
  if(!$('taskslist').visible()) {
    $('deadlines').toggle();
    $('taskslist').toggle();
    }
  recreate_sortable('taskslist');
  $('t' + id).focus();
  return false;
  }

function add_new_row(){
    Element.show('loading');
    new Ajax.Request('/task/createnew', {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(request){
            eval(request.responseText);
        }
    });
    return false;
}

function display_tasks(str){
    $('taskcontent').update(str);
    //if(tag_state.length > 0) // not sortable if the list is filtered by a tag
    //  Sortable.destroy('taskslist'); // Sortable.destroy does not work, was not documented....
}

/*
function ajax_show_project_resp(str) {
  new Ajax.Request('/task/show_project_resp/' + str, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(request){
          $('members').update(request.responseText);
      }
  });
}
*/

function ajax_select_project(str) {
  new Ajax.Request('/task/select_project/' + str, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(r){
          eval(r.responseText);
      }
  });
}

function select_project(str){
    if (str == "") return;
    $('loading').show();
    tag_state.clear();
    ajax_select_project(str);      
    return false;
}

function select_resp(str){
    if (str == "") return;
    $('loading').show();
    new Ajax.Request('/task/select_resp/' + str, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
            eval(r.responseText);
        }
    });
    return false;
}

function select_state(str){
    if (str == "") return;
    $('loading').show();
    new Ajax.Request('/task/select_state/' + str, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
            eval(r.responseText);
        }
    });
    return false;
}

function select_special(str){
    if (str == "") return;
    $('loading').show();
    new Ajax.Request('/task/select_special/' + str, {
        asynchronous: true,
        evalScripts: true,
        onComplete: function(r){
            eval(r.responseText);
        }
    });
    return false;
}

//Mouse over task's element
function mover(e, add){
    if (String(add) == "undefined") 
        add = "";
    if (add != "") 
        add = "<br/><br/><span>" + add + "</span>";
    switch (e) {
        case '':
        $('info').innerHTML = "" + add;
        break;
        case 'd':
        $('info').update("Click to indicate that this task is done" + add);
        break;
        case 'p':
        $('info').innerHTML = "Name of the project this task belongs to" + add;
        break;
        case 't':
        $('info').innerHTML = "Title of the task to do" + add;
        break;
        case 'r':
        $('info').innerHTML = "Responsible of this task" + add;
        break;
        case 'pr':
        $('info').innerHTML = "Priority of this task (number)" + add;
        break;
        case 's':
        $('info').innerHTML = "Save changes" + add;
        break;
        case 'de':
        $('info').innerHTML = "Delete permanently this task" + add;
        break;
        case 'a':
        $('info').innerHTML = "Add a new task" + add;
        break;
        case 'n':
        $('info').innerHTML = "Edit notes" + add;
        break;
        case 'da':
        $('info').innerHTML = "Task\'s due date" + add;
        break;
        case 'print':
        $('info').innerHTML = "Print tasks and subtasks" + add;
        break;
        case 'begun':
        $('info').innerHTML = "Indicates that task already begun" + add;
        break;
        case 'todo':
        $('info').innerHTML = "Indicates that task is not done" + add;
        break;
        case 'givenup':
        $('info').innerHTML = "Indicates that task has been given up" + add;
        break;
        default:
        $('info').innerHTML = "no help for " + e;
        break;
    }
}

function create_project_confirm(taskid, item_name){
    saveimg = $('s' + taskid);
    saveimg.src = '/images/save.png';
    var str = "This project does not exist.\nDo you want to create the project named '" + $('p' + taskid).value + "' ?";
    if (confirm(str)) 
        save(taskid, item_name, 1);
}

var calid;
function dispcal2(cal){
    change(calid, null);
}

function dispcal(id, value){
    calid = id;
    Calendar.setup({
        inputField: "da" + id,
        ifFormat: "%Y-%m-%d",
        showsTime: false,
        onUpdate: dispcal2
    });
}

function star_it(id) {
  new Ajax.Request('/task/star_it/' + id, {
      asynchronous: true,
      evalScripts: true,
      onComplete: function(r){
        eval(r.responseText)
      }
    });
}

function star(taskid, value){
  var img = $('st' + taskid);
  switch (value) {
    case 1:
    str = 'on';
    break;
    default:
    str = 'off';
    break;
    }
  img.src = '/images/star_' + str + '_2.gif';
  }
  
function sort_by_priority() {
  new Ajax.Request('/task/sort_by_priority/?t=' + tag_state.join(','), {
    asynchronous: true,
    evalScripts: true,
    onLoading: $('loading').show(),
    onComplete: function(r){
      $('taskcontent').update(r.responseText);
      }
    });
  }
  
function print(task_id) {
  window.open("/task/print/" + task_id);
  }
  
function quick_done(task_id) {
  var el   = $('quickdone_'+task_id);
  var done = (el.checked ? 1 : 0);
  if (el.checked) $('title_'+task_id).className = 'title_done';
  else            $('title_'+task_id).className = '';
  new Ajax.Request('/task/quick_done/'+task_id+'?d='+done, {
      asynchronous: true,
      evalScripts: true,
      onLoading:  function() {if($('loading')) $('loading').show()},
      onComplete: function(r){if($('loading')) $('loading').hide()}
    });
  }
  
function select_tab(selected_id) { // other arguments are others tab to hide
  $(selected_id).show();
  $('tab_'+selected_id).className = "tab selected";
  for (var i = 1; i < arguments.length; i++) {
    el = $(arguments[i]);
    $(arguments[i]).hide();
    $('tab_'+arguments[i]).className = "tab not_selected";
    }
  }
  
function refresh_bookmarks() {
  new Ajax.Updater('bm', '/bookmarks/list/', {asynchronous:true, evalScripts:true});
  }
  
// suggest tasks to do in a given time
function suggest() {
  new Ajax.Request('/task/suggest?t='+$('suggest_time').value, {
    asynchronous:true,
    evalScripts:true,
    onLoading:  $('loading').show(),
    onComplete: function(r){
      $('taskcontent').update(r.responseText);
      $('loading').hide();
      }

    });
  }

function show_icons(id) {
  $('icons_'+id).show();
  }
  
function hide_icons(id) {
  $('icons_'+id).hide();
  }  
